/*********************************************************************
 *
 *                  Helper Functions for Microchip TCP/IP Stack
 *
 *********************************************************************
 * FileName:        Helpers.C
 * Dependencies:    Compiler.h
 *                  Helpers.h
 * Processor:       PIC18
 * Complier:        MCC18 v1.00.50 or higher
 *                  HITECH PICC-18 V8.10PL1 or higher
 * Company:         Microchip Technology, Inc.
 *
 * Software License Agreement
 *
 * This software is owned by Microchip Technology Inc. ("Microchip") 
 * and is supplied to you for use exclusively as described in the 
 * associated software agreement.  This software is protected by 
 * software and other intellectual property laws.  Any use in 
 * violation of the software license may subject the user to criminal 
 * sanctions as well as civil liability.  Copyright 2006 Microchip
 * Technology Inc.  All rights reserved.
 *
 * This software is provided "AS IS."  MICROCHIP DISCLAIMS ALL 
 * WARRANTIES, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, NOT LIMITED 
 * TO MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND 
 * INFRINGEMENT.  Microchip shall in no event be liable for special, 
 * incidental, or consequential damages.
 *
 *
 * Author               Date    Comment
 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * Nilesh Rajbharti     5/17/01 Original        (Rev 1.0)
 * Nilesh Rajbharti     2/9/02  Cleanup
 * Nilesh Rajbharti     6/25/02 Rewritten CalcIPChecksum() to avoid
 *                              multi-byte shift operation.
 * Howard Schlunder		2/9/05	Added hexatob(), btohexa_high(), and
 *								btohexa_low()
 ********************************************************************/

#include "Def_Type.h"
#include "Utilities.h"
#include "string.h"




#ifndef NULL
  #define NULL  0
#endif


/*****************************************************************************
 Prototype    : Delay_100ns
 Description  : delay
 Input        : time
 Output       : None
 Return Value : void
 Calls        : 
 Called By    : 
 
  History        :
  1.Date         : 2014/10/17
    Author       : Mike
    Modification : Created function
 
*****************************************************************************/
//void Delay_100ns(uint8 time )
//{
//    while( time-- );
//}

#if 1
/*********************************************************************
 * Function:        BYTE hexatob(WORD_VAL AsciiChars)
 *
 * PreCondition:    None
 *
 * Input:           Two ascii bytes; each ranged '0'-'9', 'A'-'F', or
 *						'a'-'f'
 *
 * Output:          The resulting packed byte: 0x00-0xFF
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:			None
 ********************************************************************/
BYTE hexatob(WORD_VAL AsciiChars)
{
    // Convert lowercase to uppercase
    if(AsciiChars.byte.MSB_W > 'F')
        AsciiChars.byte.MSB_W -= 'a'-'A';
    if(AsciiChars.byte.LSB_W > 'F')
        AsciiChars.byte.LSB_W -= 'a'-'A';

    // Convert 0-9, A-F to 0x0-0xF
    if(AsciiChars.byte.MSB_W > '9')
        AsciiChars.byte.MSB_W -= 'A' - 10;
    else
        AsciiChars.byte.MSB_W -= '0';

    if(AsciiChars.byte.LSB_W > '9')
        AsciiChars.byte.LSB_W -= 'A' - 10;
    else
        AsciiChars.byte.LSB_W -= '0';

    // Concatenate
    return (AsciiChars.byte.MSB_W<<4) |  AsciiChars.byte.LSB_W;
}
#endif
/*********************************************************************
 * Function:        BYTE btohexa_high(BYTE b)
 *
 * PreCondition:    None
 *
 * Input:           One byte ranged 0x00-0xFF
 *
 * Output:          An ascii byte (always uppercase) between '0'-'9' 
 *					or 'A'-'F' that corresponds to the upper 4 bits of
 *					the input byte.
 *					ex: b = 0xAE, btohexa_high() returns 'A'
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:			None
 ********************************************************************/
BYTE btohexa_high(BYTE b)
{
    b >>= 4;
    return (b>0x9) ? b+'A'-10:b+'0';
}

/*********************************************************************
 * Function:        BYTE btohexa_low(BYTE b)
 *
 * PreCondition:    None
 *
 * Input:           One byte ranged 0x00-0xFF
 *
 * Output:          An ascii byte (always uppercase) between '0'-'9' 
 *					or 'A'-'F' that corresponds to the lower 4 bits of
 *					the input byte.
 *					ex: b = 0xAE, btohexa_low() returns 'E'
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:			None
 ********************************************************************/
BYTE btohexa_low(BYTE b)
{
    b &= 0x0F;
    return (b>9) ? b+'A'-10:b+'0';
}


#if 0
WORD swaps(WORD v)
{
    WORD_VAL t;
    BYTE b;

    t.Val   = v;
    b       = t.v[1];
    t.v[1]  = t.v[0];
    t.v[0]  = b;

    return t.Val;
}

DWORD swapl(DWORD v)
{
    BYTE b;
    DWORD myV;
    DWORD_VAL *myP;

    myV     = v;
    myP     = (DWORD_VAL*)&myV;

    b       = myP->v[3];
    myP->v[3] = myP->v[0];
    myP->v[0] = b;

    b       = myP->v[2];
    myP->v[2] = myP->v[1];
    myP->v[1] = b;

    return myV;

}


WORD CalcIPChecksum(BYTE* buffer, WORD count)
{
    WORD i;
    WORD *val;

    union
    {
        DWORD Val;
        struct
        {
            WORD_VAL LSB;
            WORD_VAL MSB;
        }
        words;
    } tempSum, sum;

    sum.Val = 0;

    i = count >> 1;
    val = (WORD *)buffer;

    while( i-- )
        sum.Val += *val++;

    if ( count & 1 )
        sum.Val += *(BYTE *)val;

    tempSum.Val = sum.Val;

    while( (i = tempSum.words.MSB.Val) != 0u )
    {
        sum.words.MSB.Val = 0;
        sum.Val = (DWORD)sum.words.LSB.Val + (DWORD)i;
        tempSum.Val = sum.Val;
    }

    return (~sum.words.LSB.Val);
}


/*********************************************************************
 * Function:        WORD CalcIPBufferChecksum(WORD len)
 *
 * PreCondition:    TCPInit() is already called     AND
 *                  MAC buffer pointer set to starting of buffer
 *
 * Input:           len     - Total number of bytes to calculate
 *                          checksum for.
 *
 * Output:          16-bit checksum as defined by rfc 793.
 *
 * Side Effects:    None
 *
 * Overview:        This function performs checksum calculation in
 *                  MAC buffer itself.
 *
 * Note:            None
 ********************************************************************/
#if !defined(MCHP_MAC)
WORD CalcIPBufferChecksum(WORD len)
{
    BOOL lbMSB;
    WORD_VAL checkSum;
    BYTE Checkbyte;

    lbMSB = TRUE;
    checkSum.Val = 0;

    while( len-- )
    {
        Checkbyte = MACGet();

        if ( !lbMSB )
        {
            if ( (checkSum.v[0] = Checkbyte+checkSum.v[0]) < Checkbyte)
            {
                if ( ++checkSum.v[1] == 0 )
                    checkSum.v[0]++;
            }
        }
        else
        {
            if ( (checkSum.v[1] = Checkbyte+checkSum.v[1]) < Checkbyte)
            {
                if ( ++checkSum.v[0] == 0 )
                    checkSum.v[1]++;
            }
        }

        lbMSB = !lbMSB;
    }

    checkSum.v[1] = ~checkSum.v[1];
    checkSum.v[0] = ~checkSum.v[0];
    return checkSum.Val;
}
#endif

#endif

#if 1
char *strupr (char *s)
{
    char c;
    char *t;

    t = s;
    while( (c = *t) )
    {
        if ( (c >= 'a' && c <= 'z') )
            *t -= ('a' - 'A');
        t++;
    }
    return s;
}
#endif


#if 1
void *mymemcpy(void * d1, const void * s1, register unsigned char n)
{

    register char *     d;
    register const char *   s;

    s = s1;
    d = d1;
    while(n--)
        *d++ = *s++;
    return d1;
}
#endif


#if 0
char *MemLookupMem(char*str,unsigned short int n1,char *subStr,unsigned short int n2)
{
    unsigned short int n;
    unsigned short int m;
    n = n1-n2;
    //m = n2;
    //		while( n-- )
    while (*str !='\0'&& n--)
    {
        char *p = str;
        char *q = subStr;
        char *res =NULL;
        if (*p == *q)
        {
            res = p;
            m=n2
              while (*q !='\0' && *p == *q&&m--)
              {
                  p++;
                  q++;
              }
              if (*q =='\0'||m==0)
                  return res;
        }
        str++;
    }
}
#else
/*****************************************************************************
Prototype    : MemLookupMem
Description  : lookup the s2 in buf of s1,
Input        : char*s1
unsigned short int n1  : length  of s1 to be compared
char *s2
unsigned short int n2  : length of s2 to be compared
Output       : None
Return Value : char
Calls        :
Called By    :

History        :
1.Date         : 2014/11/25
Author       : Hust
Modification : Created function

*****************************************************************************/
char *MemLookupMem(char*s1,unsigned short int n1,char *s2,unsigned short int n2)
//	(const char *s1, const char *s2)
{
    int n;
    unsigned short int l;
    //	unsigned short int m;

    l = n1-n2+1;
    if (*s2)
    {
        while (l--)
        {
            for (n=0; ( *(s1 + n) == *(s2 + n) ); n++)
            {
                //	 	m=n+1;
                if  ( n+1==n2 )
                    return (char *)s1;
            }
            s1++;
        }
        return NULL;
    }
    else
        return (char *)s1;
}

#endif


/*****************************************************************************
 Prototype    : ExtractField
 Description  : extract a segment value
 Input        : const char* pBuf
                char delimiter
                const char* field
 Output       : None
 Return Value : the field_content length
 Calls        :
 Called By    :
 
  History        :
  1.Date         : 2011/1/15
    Author       : mike
    Modification : Created function
 
*****************************************************************************/
//1   note:
//the message format should be following
//field_name=field_context--delimiter
//if end_delimiter = ';' and assign_identifier = '=' ;the setting message is "password=123456;"


unsigned char ExtractField( const char* pStr, char assgin_identifier,char end_delimiter, const char* field_name,char* field_content )
{
    unsigned char len=0;
    char* pointer1=NULL;
    char* pointer2=NULL;
    do
    {
        pointer1 = strstr(pStr,field_name);
        if(pointer1==NULL)
            break;
        pointer1 += strlen(field_name);
        pointer1 = strchr(pointer1,assgin_identifier);
        if(pointer1==NULL)
            break;
        pointer1++;
        pointer2 = strchr(pointer1,end_delimiter);
        if(pointer2==NULL)
            break;
        len = pointer2-pointer1;
        *field_content = 0;
        strncat(field_content,pointer1,len);
        //        memcpy(field_content,pointer1,pointer2-pointer1);
    }
    while ( 0 );
    return len;		//return the field_content length
}

/*****************************************************************************
 Prototype    : CheckLoopBuf_Len
 Description  : void
 Input        : None
 Output       : None
 Return Value : void
 Calls        : 
 Called By    :  read_loop_buf (  ) and write_loop_buf(  );
 when the loop buf is read or written,the check buf must be called.
 
  History        :
  1.Date         : 2014/11/23
    Author       : Hust
    Modification : Created function
 
*****************************************************************************/
#if 0
void CheckLoopBuf_Len( LOOP_BUF_STRU* p_LoopBuf )
{
    if ( p_LoopBuf->InPtr != p_LoopBuf->OutPtr)
    {
        p_LoopBuf->BufStatus = BUF_AVAILABLE;
    }
    else if( BUF_FULL != p_LoopBuf->BufStatus )
    {
        p_LoopBuf->BufStatus = BUF_FULL;
    }
    else if( BUF_EMPTY != p_LoopBuf->BufStatus )
    {

        p_LoopBuf->BufStatus = BUF_EMPTY;
    }

}
#endif

/*****************************************************************************
 Prototype    : LoopBuf_init
 Description  : initial  loop buf
 Input        : void
 Output       : None
 Return Value : void
 Calls        : 
 Called By    : 
 
  History        :
  1.Date         : 2014/11/23
    Author       : Hust
    Modification : Created function
 
*****************************************************************************/
void LoopBuf16_init( LOOP_BUF_STRU* p_LoopBuf , char* start_add,unsigned short buf_size)
{
    p_LoopBuf->StartAdd = start_add;
    p_LoopBuf->EndAdd = start_add+buf_size-1;
	p_LoopBuf->Size = buf_size;
	p_LoopBuf->step = sizeof(unsigned short);
	ResetBuf( p_LoopBuf);
}


void LoopBuf_init( LOOP_BUF_STRU* p_LoopBuf ,char* start_add,unsigned short int buf_size)
{
    p_LoopBuf->StartAdd = start_add;
    p_LoopBuf->EndAdd = start_add+buf_size-1;
	p_LoopBuf->Size = buf_size;
	ResetBuf( p_LoopBuf);
}
/*****************************************************************************
 Prototype    : ResetBuf
 Description  : reset a loop buffer
 Input        : None
 Output       : None
 Return Value : void
 Calls        : 
 Called By    : 
 
  History        :
  1.Date         : 2014/12/3
    Author       : Hust
    Modification : Created function
 
*****************************************************************************/
void ResetBuf( LOOP_BUF_STRU* p_LoopBuf)
{
    p_LoopBuf->InPtr = p_LoopBuf->StartAdd;
    p_LoopBuf->OutPtr = p_LoopBuf->StartAdd;
    memset( p_LoopBuf->StartAdd,0,p_LoopBuf->Size*p_LoopBuf->step);
    p_LoopBuf->Status = BUF_EMPTY;
}


unsigned short CheckLoopBuf_Len(LOOP_BUF_STRU* p_LoopBuf)
{
	unsigned short result;
//	if(NULL==p_LoopBuf) p_LoopBuf->Status = BUF_NA;
	switch ( p_LoopBuf->Status )
	{
	    case BUF_EMPTY:
			if(p_LoopBuf->InPtr==p_LoopBuf->OutPtr) 
			{
				result = 0;
				break;
			}
			else
				p_LoopBuf->Status = BUF_AVAILABLE;
	    case BUF_AVAILABLE:
	        if(p_LoopBuf->InPtr>p_LoopBuf->OutPtr) 
	        {
				result = (p_LoopBuf->InPtr-p_LoopBuf->OutPtr)/p_LoopBuf->step;
				break;
	        }
			else if(p_LoopBuf->InPtr<p_LoopBuf->OutPtr)
			{
				result = (p_LoopBuf->Size-(p_LoopBuf->OutPtr-p_LoopBuf->InPtr))/p_LoopBuf->step;
				break;
			}
			else 
				p_LoopBuf->Status = BUF_FULL;
	    case BUF_FULL:
	        result = p_LoopBuf->Size;
	        break;
			
		case BUF_NA:
	    default:
			result = -1;
	        
	}
	return result; 
}

/*****************************************************************************
 Prototype    : ReadLoopBuf
 Description  : read buf 
 Input        : void
 Output       : None
 Return Value : BOOL
 Calls        : 
 Called By    : 
 
  History        :
  1.Date         : 2014/11/23
    Author       : Hust
    Modification : Created function
 
*****************************************************************************/
unsigned short  ReadLoopBuf( LOOP_BUF_STRU* p_LoopBuf ,char* out_buf,unsigned short len )
{
    unsigned int temp_len;
    unsigned int actual_len=0;
    if(BUF_EMPTY != p_LoopBuf->Status)
    {
        if( p_LoopBuf->InPtr>p_LoopBuf->OutPtr)
            actual_len = p_LoopBuf->InPtr-p_LoopBuf->OutPtr;
        else
            actual_len = ( p_LoopBuf->EndAdd-p_LoopBuf->OutPtr +1)+( p_LoopBuf->InPtr-p_LoopBuf->StartAdd );
		if ( len>actual_len)	len = actual_len;
		else actual_len = len;
        while( len )
        {
            if( ( p_LoopBuf->OutPtr+len )> p_LoopBuf->EndAdd )
            {
                temp_len = p_LoopBuf->EndAdd - p_LoopBuf->OutPtr+1;
            }
            else
            {
                temp_len = len;
            }
            memcpy( out_buf,p_LoopBuf->OutPtr,temp_len);
			out_buf += temp_len;
            p_LoopBuf->OutPtr += temp_len;
            if( p_LoopBuf->OutPtr > p_LoopBuf->EndAdd )
                p_LoopBuf->OutPtr = p_LoopBuf->StartAdd;
            len -= temp_len;

            if ( p_LoopBuf->InPtr != p_LoopBuf->OutPtr)
            {
                p_LoopBuf->Status = BUF_AVAILABLE;
            }
            else if( BUF_EMPTY != p_LoopBuf->Status )
            {
                p_LoopBuf->Status = BUF_EMPTY;
            }
        }
    }
    else
        actual_len = 0;
    return actual_len;
}


/*****************************************************************************
 Prototype    : ReadLoopBuf
 Description  : read buf 
 Input        : void
 Output       : None
 Return Value : BOOL
 Calls        : 
 Called By    : 
 
  History        :
  1.Date         : 2014/11/23
    Author       : Hust
    Modification : Created function
 
*****************************************************************************/
unsigned int  ReadLoopBuf16( LOOP_BUF_STRU* p_LoopBuf ,unsigned short int* out_buf,unsigned int len )
{
    unsigned int temp_len;
    unsigned int actual_len=0;
    if(BUF_EMPTY != p_LoopBuf->Status)
    {
        if( p_LoopBuf->InPtr>p_LoopBuf->OutPtr)
            actual_len = p_LoopBuf->InPtr-p_LoopBuf->OutPtr;
        else
            actual_len = ( p_LoopBuf->EndAdd-p_LoopBuf->OutPtr +1)+( p_LoopBuf->InPtr-p_LoopBuf->StartAdd );
		if ( len>actual_len)	len = actual_len;
		else actual_len = len;
        while( len )
        {
            if( ( p_LoopBuf->OutPtr+len )> p_LoopBuf->EndAdd )
            {
                temp_len = p_LoopBuf->EndAdd - p_LoopBuf->OutPtr+1;
            }
            else
            {
                temp_len = len;
            }
            memcpy( out_buf,p_LoopBuf->OutPtr,temp_len*p_LoopBuf->step);
			out_buf += temp_len;
            p_LoopBuf->OutPtr += temp_len;
            if( p_LoopBuf->OutPtr > p_LoopBuf->EndAdd )
                p_LoopBuf->OutPtr = p_LoopBuf->StartAdd;
            len -= temp_len;

            if ( p_LoopBuf->InPtr != p_LoopBuf->OutPtr)
            {
                p_LoopBuf->Status = BUF_AVAILABLE;
            }
            else if( BUF_EMPTY != p_LoopBuf->Status )
            {
                p_LoopBuf->Status = BUF_EMPTY;
            }
        }
    }
    else
        actual_len = 0;
    return actual_len;
}


/*****************************************************************************
 Prototype    : WriteLoopBuf
 Description  : write  loop buf
 Input        : None
 Output       : None
 Return Value : BOOL
 Calls        : 
 Called By    : 
 
  History        :
  1.Date         : 2014/11/23
    Author       : Hust
    Modification : Created function
 
*****************************************************************************/
unsigned short WriteLoopBuf( LOOP_BUF_STRU* p_LoopBuf ,char* in_buf,unsigned short len )
{
    unsigned int temp_len;
    unsigned int actual_len;
    if(BUF_FULL != p_LoopBuf->Status)
    {
        if( p_LoopBuf->InPtr>=p_LoopBuf->OutPtr)
            actual_len = ( p_LoopBuf->EndAdd-p_LoopBuf->OutPtr+1 )+( p_LoopBuf->InPtr-p_LoopBuf->StartAdd );
        else
            actual_len = p_LoopBuf->InPtr-p_LoopBuf->OutPtr;
        len = actual_len;

        while( len )
        {
            if( ( p_LoopBuf->InPtr+len )> p_LoopBuf->EndAdd )
            {
                temp_len = p_LoopBuf->EndAdd - p_LoopBuf->InPtr+1;
            }
            else
            {
                temp_len = len;
            }
            memcpy( p_LoopBuf->InPtr,in_buf,temp_len);

            p_LoopBuf->InPtr += temp_len;
            if( p_LoopBuf->InPtr> p_LoopBuf->EndAdd )
                p_LoopBuf->InPtr = p_LoopBuf->StartAdd;
            len -= temp_len;

            if ( p_LoopBuf->InPtr != p_LoopBuf->OutPtr)
            {
                p_LoopBuf->Status = BUF_AVAILABLE;
            }
            else 
            {
                p_LoopBuf->Status = BUF_FULL;
            }
        }
    }
    else
        actual_len = 0;
    return actual_len;

}



/*****************************************************************************
 Prototype    : WriteLoopBuf
 Description  : write  loop buf
 Input        : None
 Output       : None
 Return Value : BOOL
 Calls        : 
 Called By    : 
 
  History        :
  1.Date         : 2014/11/23
    Author       : Hust
    Modification : Created function
 
*****************************************************************************/
unsigned short int WriteLoopBuf16( LOOP_BUF_STRU* p_LoopBuf ,unsigned short int* in_buf,unsigned short len )
{
    unsigned short int temp_len;
    unsigned short int actual_len;
    if(BUF_FULL != p_LoopBuf->Status)
    {
        if( p_LoopBuf->InPtr>=p_LoopBuf->OutPtr)
            actual_len = ( p_LoopBuf->EndAdd-p_LoopBuf->OutPtr+1 )+( p_LoopBuf->InPtr-p_LoopBuf->StartAdd );
        else
            actual_len = p_LoopBuf->InPtr-p_LoopBuf->OutPtr;
        len = actual_len;

        while( len )
        {
            if( ( p_LoopBuf->InPtr+len )> p_LoopBuf->EndAdd )
            {
                temp_len = p_LoopBuf->EndAdd - p_LoopBuf->InPtr+1;
            }
            else
            {
                temp_len = len;
            }
            memcpy( p_LoopBuf->InPtr,in_buf,temp_len*p_LoopBuf->step);

            p_LoopBuf->InPtr += temp_len;
            if( p_LoopBuf->InPtr> p_LoopBuf->EndAdd )
                p_LoopBuf->InPtr = p_LoopBuf->StartAdd;
            len -= temp_len;

            if ( p_LoopBuf->InPtr != p_LoopBuf->OutPtr)
            {
                p_LoopBuf->Status = BUF_AVAILABLE;
            }
            else 
            {
                p_LoopBuf->Status = BUF_FULL;
            }
        }
    }
    else
        actual_len = 0;
    return actual_len;

}


#if 1

/*****************************************************************************
 Prototype    : WriteLoopBuf
 Description  : write  loop buf
 Input        : None
 Output       : None
 Return Value : BOOL
 Calls        : 
 Called By    : 
 
  History        :
  1.Date         : 2014/11/23
    Author       : Hust
    Modification : Created function
 
*****************************************************************************/
LOOP_BUF_STATUS_ENUM PutByteLoopBuf( LOOP_BUF_STRU* p_LoopBuf ,char in_byte )
{
	*( p_LoopBuf->InPtr ) = in_byte;
	p_LoopBuf->InPtr ++;
	if( p_LoopBuf->InPtr> p_LoopBuf->EndAdd)
		p_LoopBuf->InPtr = p_LoopBuf->StartAdd;
//    if(BUF_FULL != p_LoopBuf->Status)
//    {

        if ((BUF_FULL != p_LoopBuf->Status)&&( p_LoopBuf->InPtr != p_LoopBuf->OutPtr))
        {
            p_LoopBuf->Status = BUF_AVAILABLE;
        }
        else 
        {
            p_LoopBuf->Status = BUF_FULL;
			p_LoopBuf->OutPtr=p_LoopBuf->InPtr ;
        }
//        return p_LoopBuf->Status;
//    }
//    else
//    {
//		p_LoopBuf->OutPtr=p_LoopBuf->InPtr ;
//    }
	return p_LoopBuf->Status;

}

#endif



unsigned short ReadRxToCh( LOOP_BUF_STRU* p_LoopBuf ,char ch,char* out_buf,unsigned short len)
{
    unsigned short copy_len;
    memset( out_buf,0,len);
    /* similar to strrch(  ) */
    copy_len=MemLookupMem(p_LoopBuf->OutPtr,p_LoopBuf->EndAdd-p_LoopBuf->OutPtr+1,&ch,1)-p_LoopBuf->OutPtr+1;

    ReadLoopBuf(p_LoopBuf,out_buf,copy_len);
    return copy_len;
}

void Delay_us(unsigned short microseconds)
{
    microseconds<<=4;
    // delay microsecond*10 cycle
    while(--microseconds);/* 5 times machine cycle */
}
#if 0
void Delay_ms(int milliseconds)
{
	int microseconds;
	while( milliseconds--) /* for n times do: */
    {
		microseconds=1600;
         while(--microseconds);
    }

}
#else
unsigned long gDelayCount=0;
void Delay_ms(int milliseconds)
{
	gDelayCount=milliseconds;
	while( gDelayCount) ;/* for n times do: */
}


#endif

